
package com.zy.je.common.core.utils.lang;

import com.zy.je.common.core.constant.StringPool;
import com.zy.je.common.core.utils.collect.ListUtil;
import org.apache.logging.log4j.message.ParameterizedMessageFactory;
import org.dromara.hutool.core.codec.binary.Base64;
import org.dromara.hutool.crypto.digest.MD5;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

/**
 * 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
 *
 * @author zy
 */
public class StringUtil extends org.apache.commons.lang3.StringUtils {

    private static final char SEPARATOR = '_';
    private static final String CHARSET_NAME = "UTF-8";

    /**
     * 转换为字节数组
     *
     * @param str
     * @return
     */
    public static byte[] getBytes(String str) {
        if (str != null) {
            try {
                return str.getBytes(CHARSET_NAME);
            } catch (UnsupportedEncodingException e) {
                return null;
            }
        } else {
            return null;
        }
    }

    /**
     * 转换为字节数组
     *
     * @param bytes
     * @return
     */
    public static String toString(byte[] bytes) {
        try {
            return new String(bytes, CHARSET_NAME);
        } catch (UnsupportedEncodingException e) {
            return EMPTY;
        }
    }

    /**
     * 是否包含字符串
     *
     * @param str  验证字符串
     * @param strs 字符串组
     * @return 包含返回true
     */
    public static boolean inString(String str, String... strs) {
        if (str != null && strs != null) {
            for (String s : strs) {
                if (str.equals(trim(s))) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 是否包含字符串
     *
     * @param str  验证字符串
     * @param strs 字符串组
     * @return 包含返回true
     */
    public static boolean inStringIgnoreCase(String str, String... strs) {
        if (str != null && strs != null) {
            for (String s : strs) {
                if (str.equalsIgnoreCase(trim(s))) {
                    return true;
                }
            }
        }
        return false;
    }
//
//    /**
//     * 替换掉HTML标签方法
//     */
//    public static String stripHtml(String html) {
//        if (isBlank(html)) {
//            return "";
//        }
//        // html.replaceAll("\\&[a-zA-Z]{0,9};", "").replaceAll("<[^>]*>", "");
//        String regEx = "<.+?>";
//        Pattern p = Pattern.compile(regEx);
//        Matcher m = p.matcher(html);
//        String s = m.replaceAll("");
//        return s;
//    }


    /**
     * 驼峰命名法工具
     * !!!注意：此方法多次调用会有副作用，最终会将所有大写转成小写
     *
     * @return camelCase(" hello_world ") == "helloWorld" capCamelCase("hello_world")
     * == "HelloWorld" uncamelCase("helloWorld") = "hello_world"
     */
    public static String camelCase(String s) {
        if (s == null) {
            return null;
        }

        s = s.toLowerCase();

        StringBuilder sb = new StringBuilder(s.length());
        boolean upperCase = false;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            if (c == SEPARATOR) {
                upperCase = true;
            } else if (upperCase) {
                sb.append(Character.toUpperCase(c));
                upperCase = false;
            } else {
                sb.append(c);
            }
        }

        return sb.toString();
    }

    /**
     * 驼峰命名法工具
     *
     * @return camelCase(" hello_world ") == "helloWorld" capCamelCase("hello_world")
     * == "HelloWorld" uncamelCase("helloWorld") = "hello_world"
     */
    public static String capCamelCase(String s) {
        return toCapCamelCase(uncamelCase(s));
    }

    private static String toCapCamelCase(String s) {
        if (s == null) {
            return null;
        }
        s = camelCase(s);
        return s.substring(0, 1).toUpperCase() + s.substring(1);
    }


    /**
     * 驼峰命名法工具
     *
     * @return camelCase(" hello_world ") == "helloWorld" capCamelCase("hello_world")
     * == "HelloWorld" uncamelCase("helloWorld") = "hello_world"
     */
    public static String uncamelCase(String s) {
        if (s == null) {
            return null;
        }

        StringBuilder sb = new StringBuilder();
        boolean upperCase = false;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            boolean nextUpperCase = true;

            if (i < (s.length() - 1)) {
                nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
            }

            if ((i > 0) && Character.isUpperCase(c)) {
                if (!upperCase || !nextUpperCase) {
                    sb.append(SEPARATOR);
                }
                upperCase = true;
            } else {
                upperCase = false;
            }

            sb.append(Character.toLowerCase(c));
        }

        return sb.toString();
    }


    /**
     * 获取随机字符串
     *
     * @param count
     * @return
     */
    public static String getRandomStr(int count) {
        char[] codeSeq = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
                'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
        Random random = new Random();
        StringBuilder s = new StringBuilder();
        for (int i = 0; i < count; i++) {
            String r = String.valueOf(codeSeq[random.nextInt(codeSeq.length)]);
            s.append(r);
        }
        return s.toString();
    }

    /**
     * 获取随机数字
     *
     * @param count
     * @return
     */
    public static String getRandomNum(int count) {
        char[] codeSeq = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
        Random random = new Random();
        StringBuilder s = new StringBuilder();
        for (int i = 0; i < count; i++) {
            String r = String.valueOf(codeSeq[random.nextInt(codeSeq.length)]);
            s.append(r);
        }
        return s.toString();
    }


    /**
     * 获取随机数
     *
     * @param min
     * @param max
     * @return
     */
    public static int getRandomNum(int min, int max) {

        return (int) (min + Math.random() * (max - min));
    }

    /**
     * 获取树节点名字
     *
     * @param isShowCode 是否显示编码<br>
     *                   true or 1：显示在左侧：(code)name<br>
     *                   2：显示在右侧：name(code)<br>
     *                   false or null：不显示编码：name
     * @param code       编码
     * @param name       名称
     * @return
     */
    public static String getTreeNodeName(String isShowCode, String code, String name) {
        if ("true".equals(isShowCode) || "1".equals(isShowCode)) {
            return "(" + code + ") " + StringUtil.replace(name, " ", "");
        } else if ("2".equals(isShowCode)) {
            return StringUtil.replace(name, " ", "") + " (" + code + ")";
        } else {
            return StringUtil.replace(name, " ", "");
        }
    }

    /**
     * 截取字符串，无异常的截取。如果指定定的范围超过字符串长度，则按以下规则重新计算：当开始位置超出时，开始位置最小为首字符位置；当结束位置超出时，结束位置最大为最后一个字符位置
     *
     * @param src
     * @param start
     * @param end
     * @return
     */
    public static String subString(String src, Integer start, Integer end) {
        if (null == src) {
            return null;
        }
        int indexFrom = start == null ? 0 : start;
        int indexTo = end == null ? src.length() : end;
        if (indexTo > src.length()) {
            indexTo = src.length();
        }
        if (indexFrom < 0 || indexTo < 0 || indexFrom > indexTo || indexFrom >= src.length()) {
            return null;
        }

        return src.substring(indexFrom, indexTo);
    }

    /**
     * 格式化数值格式，保留指定小数位，空数据则返回-
     */
    public static String formatToNumber(String val, int scale) {
        if (StringUtil.isBlank(val)) {
            return "-";
        }
        return NumberUtil.formatToNumber(val, scale);
    }

    /**
     * 格式化数值格式，保留指定小数位，空数据则返回-
     */
    public static String numberFormat(String value, String format) {
        if (StringUtil.isBlank(value)) {
            return "";
        }
        String formatStr = format;
        if (StringUtil.isBlank(format)) {
            formatStr = "#.#########";
        }
        DecimalFormat df = new DecimalFormat(formatStr);
        double f = ObjectUtil.toDouble(value);
        return df.format(f);
    }

    /**
     * 格式化数值格式，保留指定小数位，空数据则返回-
     */
    public static String numberToMoneyFormat(String value) {
        return numberFormat(value, "###,##0.00");
    }

    /**
     * 去掉空格、回车、换行、制表符
     *
     * @param str
     * @return
     */
   private static Pattern p = Pattern.compile("\\s*|\t|\r|\n");
    public static String deleteInvisibleChar(String str) {
        String dest = "";
        if (str != null) {
            Matcher m = p.matcher(str);
            dest = m.replaceAll("");
        }
        return dest;
    }

    /**
     * 字符串替换
     *
     * @param str
     * @param separatorChars
     * @param replaceParam
     * @return
     */
    public static String replaceStr(String str, String separatorChars, Map<String, String> replaceParam) {
        if (str == null || str == "" || replaceParam == null) {
            return str;
        }

        if (separatorChars == null) {
            separatorChars = "";
        }

        for (Map.Entry<String, String> entry : replaceParam.entrySet()) {

            str = str.replace(separatorChars.concat(entry.getKey()).concat(separatorChars),
                    string2Json(ObjectUtil.toString(entry.getValue())));
        }

        return str;
    }

    /**
     * JSON字符串特殊字符处理，比如：“\A1;1300”
     *
     * @param s
     * @return String
     */
    private static String string2Json(String s) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            switch (c) {
                case '\"':
                    sb.append("\\\"");
                    break;
                case '\\':
                    sb.append("\\\\");
                    break;
                case '/':
                    sb.append("\\/");
                    break;
                case '\b':
                    sb.append("\\b");
                    break;
                case '\f':
                    sb.append("\\f");
                    break;
                case '\n':
                    sb.append("\\n");
                    break;
                case '\r':
                    sb.append("\\r");
                    break;
                case '\t':
                    sb.append("\\t");
                    break;
                default:
                    sb.append(c);
            }
        }
        return sb.toString();
    }

    public static String encryptString(String src, int encryLength) {
        if (isBlank(src) || src.length() < 3) {
            int minEncryLenght = 4;
//            if(encryLength>minEncryLenght){
//                minEncryLenght = encryLength;
//            }
            return IntStream.range(0, minEncryLenght).boxed()
                    .map(i -> {
                        return "*";
                    })
                    .collect(Collectors.joining(""));
        }

        List<String> s = ListUtil.newArrayList(src.split(""));
        //3-4位，前后留一位
        if (s.size() <= 2 + encryLength) {
            //中间位置为[1,size-1]
            return IntStream.range(0, 2 + encryLength).boxed()
                    .map(i -> {
                        if (i == 0) {
                            return s.get(0);
                        } else if (i == encryLength + 1) {
                            return s.get(s.size() - 1);
                        } else {
                            return "*";
                        }
                    })
                    .collect(Collectors.joining(""));
        }

        //中间位置为[1,size-1]
        return IntStream.range(0, s.size()).boxed()
                .map(i -> {
                    if (i >= ((s.size() - encryLength) / 2 ) && i <= ((s.size() - encryLength) / 2) + encryLength-1) {
                        return "*";
                    }
                    return s.get(i);
                })
                .collect(Collectors.joining(""));
    }

    /**
     * 首字母大写
     *
     * @param str
     * @return
     */
    public static String upperFirstCase(String str) {
        if (str == null) {
            return null;
        }
        char[] ch = str.toCharArray();
        if (ch[0] >= 'a' && ch[0] <= 'z') {
            ch[0] = (char) (ch[0] - 32);
        }
        return new String(ch);
    }

    /**
     * 格式化拼串的字符串
     *
     * @param src
     * @return
     */
    public static String formatSortedJoinString(String src) {
        String f = ListUtil.splitStringToSet(src).stream()
                .sorted()
                .collect(Collectors.joining(StringPool.COMMA));
        if (!f.startsWith(StringPool.COMMA)) {
            f = StringPool.COMMA + f;
        }
        if (!f.endsWith(StringPool.COMMA)) {
            f = f + StringPool.COMMA;
        }
        return f;

    }

    /**
     * 字符格式化，形如:xxx{p1},yyy{p2}
     *
     * @param src
     * @param params
     * @return
     */
    public static String fmtWithParam(final String src, final Object... params) {
        return new ParameterizedMessageFactory()
                .newMessage(src, params)
                .getFormattedMessage();
    }


    /**
     * 对字符串进md5 hash，取中间16位，再转成36进制字符串(小写字母+数字)返回
     *
     * @param str
     * @return
     */
    public static String shortMd5Radix36(String str) {
        String md5Enc16 = MD5.of().digestHex(str).substring(8, 24);
        //再转成36进制
        return NumberUtil.numToRadix36(md5Enc16, 16);
    }

    /**
     * 使用gzip压缩字符串
     *
     * @param originString 要压缩的字符串
     * @return 压缩后的字符串
     */
    public static String compress(String originString) {
        if (originString == null || originString.length() == 0) {
            return originString;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try (
                GZIPOutputStream gzip = new GZIPOutputStream(out);
        ) {
            gzip.write(originString.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Base64.encode(out.toByteArray());
    }

    /**
     * 使用gzip解压缩
     *
     * @param compressedString 压缩字符串
     * @return
     */
    public static String decompress(String compressedString) {
        if (compressedString == null || compressedString.length() == 0) {
            return null;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        byte[] compressedByte = new byte[0];
        try {
            compressedByte = Base64.decode(compressedString);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String originString = null;
        try (
                ByteArrayInputStream in = new ByteArrayInputStream(compressedByte);
                GZIPInputStream ginzip = new GZIPInputStream(in);
        ) {
            byte[] buffer = new byte[1024];
            int offset = -1;
            while ((offset = ginzip.read(buffer)) != -1) {
                out.write(buffer, 0, offset);
            }
            originString = out.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return originString;
    }

    public static void main(String[] args) {
        String t = "";
        List<String> s = ListUtil.newArrayList(t.split(","));

        int encyLenght = 5;
        System.out.println(encryptString("", encyLenght));
        System.out.println(encryptString("1", encyLenght));
        System.out.println(encryptString("12", encyLenght));
        System.out.println(encryptString("123", encyLenght));
        System.out.println(encryptString("1234", encyLenght));
        System.out.println(encryptString("12345", encyLenght));
        System.out.println(encryptString("123456", encyLenght));
        System.out.println(encryptString("1234567", encyLenght));
        System.out.println(encryptString("12345678", encyLenght));
        System.out.println(encryptString("123456789", encyLenght));
        System.out.println(encryptString("1234567890", encyLenght));
        System.out.println(encryptString("1234567890a", encyLenght));
        System.out.println(encryptString("1234567890ab", encyLenght));
        System.out.println(encryptString("1234567890abcdefghigk", encyLenght));
    }

    // /**
    // * 测试代码
    // * @param args
    // */
    // public static void main(String[] args) {
    // String html = "<p style=\"text-align: left; padding-bottom: 0px;
    // text-transform: none; background-color: rgb(255,255,255); text-indent: 0px;
    // margin: 0px; padding-left: 0px; letter-spacing: normal; padding-right: 0px;
    // font: 14px/25px 宋体, tahoma, arial, sans-serif; white-space: normal; color:
    // rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-stroke-width:
    // 0px\">__eol__
    // 科技日报讯&nbsp;（通讯员辛志向&nbsp;记者王建高）日前，青岛高新区国家级生态工业示范园区通过了由国家环保部及科技部、商务部三部门联合组织的国家正式验收。</p>__eol__<p
    // style=\"text-align: left; padding-bottom: 0px; text-transform: none;
    // background-color: rgb(255,255,255); text-indent: 0px; margin: 0px;
    // padding-left: 0px; letter-spacing: normal; padding-right: 0px; font:
    // 14px/25px 宋体, tahoma, arial, sans-serif; white-space: normal; color:
    // rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-stroke-width:
    // 0px\">__eol__
    // &nbsp;&nbsp;&nbsp;&nbsp;青岛市委常委、红岛经济区工委书记、管委主任陈飞介绍，建立国家生态工业示范园区是青岛高新区深化和拓展生态创建成果，加快结构调整，推进转型发展，进而辐射带动红岛经济区生态建设的重要抓手。</p>__eol__<p
    // style=\"text-align: left; padding-bottom: 0px; text-transform: none;
    // background-color: rgb(255,255,255); text-indent: 0px; margin: 0px;
    // padding-left: 0px; letter-spacing: normal; padding-right: 0px; font:
    // 14px/25px 宋体, tahoma, arial, sans-serif; white-space: normal; color:
    // rgb(0,0,0); word-spacing: 0px; padding-top: 0px; -webkit-text-stroke-width:
    // 0px\">__eol__
    // &nbsp;&nbsp;&nbsp;&nbsp;自2007年经国家三部委批准创建以来，青岛高新区高度重视，强化措施，始终按照创建工作要求，坚持生态、生活、生产&ldquo;三生共融&rdquo;理念，以生态环境的优化带动经济的发展。创建过程中，坚持&ldquo;科学性规划，高水平建设，生态化发展&rdquo;的原则，实施&ldquo;国际化、高端化、低碳化&rdquo;三大战略，逐步建立起适应循环经济发展的产业体系和政策体系，形成了完善的生态工业园建设框架和循环经济发展机制，实现了经济高速发展与环境持续改善的良性循环。随着发展环境和核心竞争力的不断提升，通过了ISO14001环境管理体系认证，获得了中国最具投资潜力经济园区、国家科技兴贸创新基地、山东省海外高层次人才创新创业基地等称号，在国家级高新区综合评价中连续多年跻身前列，已经成为山东半岛乃至环渤海区域快速成长、极具创新活力和竞争力的蓝色经济特色高科技产业园区。</p>";
    // html += "<div style=\"text-indent: 32pt\">__eol__ <span style=\"line-height:
    // 20px; font-size: 20px\"><span style=\"font-family:
    // 宋体\">我市积极支持和引导企业、高校院所&ldquo;走出去&rdquo;开展国际科技合作，在国外集聚和利用各种创新资源，增强我市企业和科研院所竞争实力。</span></span></div>__eol__<div
    // align=\"left\" style=\"text-align: left; text-indent: 32pt; text-autospace:
    // \">__eol__ <span style=\"line-height: 20px; font-size: 20px\"><span
    // style=\"font-family:
    // 宋体\">一是在国外设立研发中心。通过合资、并购、控股等方式，在国外设立研发中心和产业园，传播中国文化，提升青岛声誉。如，软控在斯洛伐克设立的研发中心成为我国与中东欧国家合作的成功样板。南车青岛四方积极筹建与泰国等高铁联合研发中心，将成为我国高端成套装备出口的重要研发基地。<span
    // style=\"color: black\">2013</span><span style=\"color:
    // black\">年，我市企业与大学科研机构与国外共建7家联合研发中心。 </span></span></span></div>__eol__<div
    // style=\"text-indent: 32pt\">__eol__ <span style=\"line-height: 20px;
    // font-size: 20px\"><span style=\"font-family: 宋体\"><span style=\"color:
    // black\">二是利用科技资源和渠道助推中小科技企业&ldquo;走出去&rdquo;开发新兴市场。</span><span
    // style=\"color:
    // black\">利用尼日利亚总统访华契机，积极向尼方政府代表团推介我市现代农业技术和先进制造业企业。引导我市科技型企业输出技术，拓展西非共同体市场，推动企业转型升级，拓宽&ldquo;走出去&rdquo;渠道</span><span
    // style=\"color: black\">。</span></span></span></div>";
    // html += "<p style='TEXT-ALIGN: center'
    // class=\"sdfasf\"><strong>蓝海技术加以</strong></p><p style='TEXT-ALIGN:
    // center'><em>蓝海技术加以</em></p><p style='TEXT-ALIGN: center'><span
    // style='TEXT-DECORATION: underline'>蓝海技术加以</span></p><p style='TEXT-ALIGN:
    // center'>蓝海技术加以</p><p></p>";
    // html = html.replaceAll("__eol__", "");
    // System.out.println(replaceMobileHtml(html));
    // }

}
